#include "dvbinner.h"

typedef enum __DVB_PLAY_EVENT_s
{
	START_PLAY,
	PAT_RECIEVED,
	PMT_RECIEVED,
	STOP_PLAY,
}DVB_PLAY_EVENT_e;

typedef struct
{
	DVB_PLAY_EVENT_e m_eType;
	union
	{
		play_control_param_t 	m_stPlayParam;
		unsigned char			m_au8Data[1024];
	}m_uData;
}play_control_msg_t;

typedef enum
{
	DVB_PLAY_STOP,
	DVB_PLAY_RECV_PAT,
	DVB_PLAY_RECV_PMT,
	DVB_PLAY_PLAYING,
}DVB_PLAY_CONTROL_STATE_T;

typedef struct
{
	DVB_PLAY_CONTROL_STATE_T 	m_eState;
	unsigned int					m_u32CapmtSended;
	unsigned int 					m_u32PmtCrc;
	play_control_param_t			m_stCurPlayParam;
}play_control_manager_t;

dvb_handle_t hMsgquePlayControl = (dvb_handle_t)NULL;
dvb_handle_t hPlayControlFilter = DVB_INVALID_HANDLE;
unsigned int s_u32PmtCrc = 0;

int DvbPlayControlPatReceived( dvb_handle_t hFilter,  unsigned char* pu8Data,  unsigned short u16Datalen)
{
	int ret;
	play_control_msg_t stMsg;

	mwDebug("DvbPlayControlPatReceived() - entry, hFilter = 0x%x, pu8Data = %p, u16Datalen = %d\r\n", hFilter, pu8Data, u16Datalen);
	stMsg.m_eType = PAT_RECIEVED;
	memcpy(stMsg.m_uData.m_au8Data, pu8Data, u16Datalen);
	ret = mwOsSendMessage(hMsgquePlayControl, &stMsg, sizeof(stMsg), 0);
	if(ret != 0)
	{
		mwDebug("DvbPlayControlPatReceived() - call mwOsSendMessage ret=%d\n",ret);
	}
	mwDebug("DvbPlayControlPatReceived() - ret, ret = %d\r\n", ret);
	
	return ret;
}

static int DvbPlayControlRecvPat()
{
	int ret = 0;
	filter_param_t filterParam;
	unsigned short SecByte[16];

	mwDebug("DvbPlayControlRecvPat() - entry\r\n");
	if(hPlayControlFilter != DVB_INVALID_HANDLE)
		mwDmxStopFilter(hPlayControlFilter);
	
	memset(SecByte,0,16*2);
	SecByte[0] = SIPSI_TID_PAT + (0xFF<<8);
	filterParam.m_u8CrcCheck = 1;
	filterParam.m_u8FilterDepth = 1;
	filterParam.m_pfCb = DvbPlayControlPatReceived;
	filterParam.m_u16Pid = SIPSI_PID_PAT;
	filterParam.m_pu16SectByte = SecByte;
	filterParam.m_hQueueID = (dvb_handle_t)NULL;
	ret=mwDmxStartFilter(&filterParam,&hPlayControlFilter);
	if(ret != 0)
	{
		mwError("DvbPlayControlRecvPat() - start filter failed\r\n");
		hPlayControlFilter = DVB_INVALID_HANDLE;
	}
	mwDebug("DvbPlayControlRecvPat() - return, ret = %d\r\n", ret);
	return ret;
}

int DvbPlayControlPmtReceived( dvb_handle_t hFilter,  unsigned char* pu8Data,  unsigned short u16Datalen)
{
	int ret = 0;
	unsigned int u32Crc;
	play_control_msg_t stMsg;

	//mwDebug("DvbPlayControlPmtReceived() - entry, hFilter = 0x%x, pu8Data = %p, u16Datalen = %d\r\n", hFilter, pu8Data, u16Datalen);
	u32Crc = SiPsiGetSectionCrc(pu8Data);
	if(s_u32PmtCrc != u32Crc)
	{
		mwDebug("DvbPlayControlPmtReceived entry, send to playcontrol task\r\n");
		stMsg.m_eType = PMT_RECIEVED;
		memcpy(stMsg.m_uData.m_au8Data, pu8Data, u16Datalen);
		ret = mwOsSendMessage(hMsgquePlayControl, &stMsg, sizeof(stMsg), 0);
		if(ret != 0)
		{
			mwDebug("DvbPlayControlPmtReceived call mwOsSendMessage ret=%d\n",ret);
		}
		s_u32PmtCrc = u32Crc;
	}
	//mwDebug("DvbPlayControlPmtReceived() - return, ret = %d\r\n", ret);

	return ret;
}

static int DvbPlayControlRecvPmt(unsigned short u16PmtPid, unsigned short u16ServiceId)
{
	int ret = 0;
	filter_param_t filterParam;
	unsigned short SecByte[16];

	mwDebug("DvbPlayControlRecvPmt() - entry, u16PmtPid = %d, u16ServiceId = %d\r\n", u16PmtPid, u16ServiceId);
	if(hPlayControlFilter != DVB_INVALID_HANDLE)
		mwDmxStopFilter(hPlayControlFilter);
	
	s_u32PmtCrc = 0;
	memset(SecByte,0,16*2);
	SecByte[0] = SIPSI_TID_PMT + (0xFF<<8);
	SecByte[3] = ((u16ServiceId>>8)&0xFF) + (0xFF<<8);
	SecByte[4] = (u16ServiceId&0xFF) + (0xFF<<8);
	filterParam.m_u8CrcCheck = 1;
	filterParam.m_u8FilterDepth = 5;
	filterParam.m_pfCb = DvbPlayControlPmtReceived;
	filterParam.m_u16Pid = u16PmtPid;
	filterParam.m_pu16SectByte = SecByte;
	filterParam.m_hQueueID = (dvb_handle_t)NULL;
	ret=mwDmxStartFilter(&filterParam,&hPlayControlFilter);
	if(ret != 0)
	{
		mwError("DvbPlayControlRecvPmt() - start filter failed\r\n");
		hPlayControlFilter = DVB_INVALID_HANDLE;
	}
	mwDebug("DvbPlayControlRecvPmt() - return, ret = %d\r\n", ret);
	return ret;
}

static int DvbPlayControlStopPatPmt()
{
	int ret = 0;
	
	mwDebug("DvbPlayControlStopPatPmt() - entry\r\n");
	if(hPlayControlFilter != DVB_INVALID_HANDLE)
		ret = mwDmxStopFilter(hPlayControlFilter);
	hPlayControlFilter = DVB_INVALID_HANDLE;
	mwDebug("DvbPlayControlStopPatPmt() - return, ret = %d\r\n", ret);
	return ret;
}

int DvbPlayControlGetPmtPid(unsigned char* pu8Data, unsigned short u16Serviceid, unsigned short* pu16PmtPid)
{
	unsigned int u32ProgNum;
	unsigned int i;
	sipsi_program_t stProg;
	int s32Ret = -1;

	mwDebug("DvbPlayControlGetPmtPid() - entry - pu8Data = %p, u16Serviceid = %d\r\n", pu8Data, u16Serviceid);
	*pu16PmtPid = 0;
	u32ProgNum = SiPsiPATGetProgramCount(pu8Data);
	for(i=0; i<u32ProgNum; i++)
	{
		SiPsiPATGetProgram(pu8Data, &stProg, i);
		mwDebug("DvbPlayControlGetPmtPid() - stProg[%d][%d, %d]\r\n", i, stProg.m_u16ProgNum, stProg.m_u16PmtPid);
		if(stProg.m_u16ProgNum == u16Serviceid)
		{
			*pu16PmtPid = stProg.m_u16PmtPid;
			s32Ret = 0;
			mwDebug("DvbPlayControlGetPmtPid() - get pmt pid ok *pu16PmtPid = %d\r\n", *pu16PmtPid);
			break;
		}
	}
	mwDebug("DvbPlayControlGetPmtPid() - return s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}


//return:0-replay please, -1-do not need replay
static int DvbPlayControlNeedReplay(play_control_param_t* pstPlayParam, unsigned char* pu8Pmt)
{
	unsigned short u16ServiceId;
	unsigned int u32Cnt;
	unsigned int i;
	sipsi_prog_element_t stProg;
	unsigned short u16VidPid = 0, u16VidType;
	unsigned short u16AudPid = 0, u16AudType;
	unsigned short u16PrivateEsPid = 0;
	unsigned short u16PcrPid = 0;
	int ret = -1;
	char* ps8RegisterationDesc;	

	mwDebug("DvbPlayControlNeedReplay() - entry, pstPlayParam = %p, pu8Pmt = %p\r\n", pstPlayParam, pu8Pmt);
	u16ServiceId = SiPsiPMTGetServiceID(pu8Pmt);
	if(u16ServiceId == pstPlayParam->handle.serviceId)
	{
		u32Cnt=SiPsiPMTGetElementCount(pu8Pmt);
		for(i=0; i<u32Cnt; i++)
		{
			SiPsiPMTGetElement(pu8Pmt,&stProg,i);
			switch(stProg.m_u8StreamType)
			{
				case SIPSI_ES_TYPE_MPEG1_VIDEO:
				case SIPSI_ES_TYPE_MPEG2_VIDEO:
				case SIPSI_ES_TYPE_MPEG4_VIDEO:
				case SIPSI_ES_TYPE_VIDEO_HEVC:
				case SIPSI_ES_TYPE_VIDEO_CAVS:
					u16VidPid = stProg.m_u16ElementaryPid;
					u16VidType = stProg.m_u8StreamType;
					break;
				case SIPSI_ES_TYPE_MPEG1_AUDIO:
				case SIPSI_ES_TYPE_MPEG2_AUDIO:
				case SIPSI_ES_TYPE_AAC:
				case SIPSI_ES_TYPE_AAC1:
				case SIPSI_ATSC_DOLBY_DIGITAL:
				case SIPSI_ES_TYPE_DTS_AUDIO:
					if(u16AudPid == 0)
					{
						u16AudPid = stProg.m_u16ElementaryPid;
						u16AudType = stProg.m_u8StreamType;
					}
					break;
				case SIPSI_ES_TYPE_PRIVATE_PES:
					if(SiPsiFindDescriptor(stProg.m_pu8Descriptors, stProg.m_u16EsInfoLength, SIPSI_DESCTAG_AC3))
					{
						if(u16AudPid == 0)
						{
							u16AudPid = stProg.m_u16ElementaryPid;
							u16AudType = stProg.m_u8StreamType;
						}
					}
					else if(SiPsiFindDescriptor(stProg.m_pu8Descriptors, stProg.m_u16EsInfoLength, SIPSI_DESCTAG_REGISTERATION))
					{
						ps8RegisterationDesc = SiPsiFindDescriptor(stProg.m_pu8Descriptors, stProg.m_u16EsInfoLength, SIPSI_DESCTAG_REGISTERATION);
						if(ps8RegisterationDesc[1]==4 && ps8RegisterationDesc[2]=='H' && ps8RegisterationDesc[3]=='E' && ps8RegisterationDesc[4]=='V' && ps8RegisterationDesc[5]=='C')
						{
							u16VidPid = stProg.m_u16ElementaryPid;
							u16VidType = SIPSI_ES_TYPE_VIDEO_HEVC;
						}
						else if((ps8RegisterationDesc[1]==4 && ps8RegisterationDesc[2]=='A' && ps8RegisterationDesc[3]=='V' && ps8RegisterationDesc[4]=='S' && ps8RegisterationDesc[5]=='V'))
						{
							u16VidPid = stProg.m_u16ElementaryPid;
							u16VidType = SIPSI_ES_TYPE_VIDEO_CAVS;
						}
						else if( ps8RegisterationDesc[1]==4 && (ps8RegisterationDesc[2]=='A' && ps8RegisterationDesc[3]=='C' && ps8RegisterationDesc[4]=='-' && ps8RegisterationDesc[5]=='3')
							|| (ps8RegisterationDesc[2]=='D' && ps8RegisterationDesc[3]=='T' && ps8RegisterationDesc[4]=='S' && ps8RegisterationDesc[5]=='1')
							|| (ps8RegisterationDesc[2]=='D' && ps8RegisterationDesc[3]=='T' && ps8RegisterationDesc[4]=='S' && ps8RegisterationDesc[5]=='2')
							|| (ps8RegisterationDesc[2]=='D' && ps8RegisterationDesc[3]=='T' && ps8RegisterationDesc[4]=='S' && ps8RegisterationDesc[5]=='3')
							|| (ps8RegisterationDesc[2]=='E' && ps8RegisterationDesc[3]=='A' && ps8RegisterationDesc[4]=='C' && ps8RegisterationDesc[5]=='3')
							|| (ps8RegisterationDesc[2]=='D' && ps8RegisterationDesc[3]=='R' && ps8RegisterationDesc[4]=='A' && ps8RegisterationDesc[5]=='1'))
						{
							u16AudPid = stProg.m_u16ElementaryPid;
							u16AudType = stProg.m_u8StreamType;
						}
						else if(u16PrivateEsPid == 0)
						{
							u16PrivateEsPid = stProg.m_u16ElementaryPid;
						}
					}
					else if(u16PrivateEsPid == 0)
					{
						u16PrivateEsPid = stProg.m_u16ElementaryPid;
					}
					break;
				default:
					break;
			}
		}
		if(u16PcrPid == 0)
			u16PcrPid = SiPsiPMTGetPCRPID(pu8Pmt);

		if(u16AudPid == 0)
		{
			u16AudPid = u16PrivateEsPid;
			u16AudType = SIPSI_ES_TYPE_PRIVATE_PES;
		}

		if(u16VidPid!=pstPlayParam->vPid || u16VidType!=pstPlayParam->vType
			||u16AudPid!=pstPlayParam->aPid || u16AudType!=pstPlayParam->aType
			|| u16PcrPid!=pstPlayParam->pPid)
		{
			mwDebug("DvbPlayControlNeedReplay return replay, old[0x%x, 0x%x, 0x%x, 0x%x, 0x%x], new[0x%x, 0x%x, 0x%x, 0x%x, 0x%x]\r\n", 
				pstPlayParam->vPid, pstPlayParam->vType, pstPlayParam->aPid, pstPlayParam->aType, pstPlayParam->pPid, u16VidPid, u16VidType, u16AudPid, u16AudType, u16PcrPid);
			pstPlayParam->vPid = u16VidPid;
			pstPlayParam->vType = u16VidType;
			pstPlayParam->aPid = u16AudPid;
			pstPlayParam->aType = u16AudType;
			pstPlayParam->pPid = u16PcrPid;
			ret = 0;
		}
	}
	mwDebug("DvbPlayControlNeedReplay() - return, ret = %d\r\n", ret);
	return ret;
}

//0-same, 1-different
int DvbPlayControlCheckProgram(play_control_param_t* pstNew, play_control_param_t* pstOld)
{
	int s32Ret = 0;
	
	if(pstNew->handle.frequence!=pstOld->handle.frequence || pstNew->handle.netId!=pstOld->handle.netId
		|| pstNew->handle.serviceId!=pstOld->handle.serviceId || pstNew->handle.tsId!=pstOld->handle.tsId)
	{
		s32Ret = 1;
	}
	else if(pstNew->tunerInfo.bandwidth!=pstOld->tunerInfo.bandwidth || pstNew->tunerInfo.frequency!=pstOld->tunerInfo.frequency
		|| pstNew->tunerInfo.modulation!=pstOld->tunerInfo.modulation || pstNew->tunerInfo.symbol_rate!=pstOld->tunerInfo.symbol_rate)
	{
		s32Ret = 1;
	}
	
	return s32Ret;
}

int DvbPlayControlStartMsg(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = -1;
	dvb_service_t* ServiceHandle;
	unsigned short u16PmtPid;

	mwDebug("DvbPlayControlStartMsg() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	if(DvbPlayControlCheckProgram(&pstMsg->m_uData.m_stPlayParam, &pstManager->m_stCurPlayParam) != 0)
	{
		DvbBuilderMonitorSearchStop();
		ServiceHandle = &pstMsg->m_uData.m_stPlayParam.handle;
		if(DVBTunerLock(&pstMsg->m_uData.m_stPlayParam.tunerInfo))
		{
			mwDebug("DvbPlayControlStartMsg() - DVBTunerLock not ok\r\n");
			if(pstMsg->m_uData.m_stPlayParam.callback)
				pstMsg->m_uData.m_stPlayParam.callback(SERVICE_LOCK_FAIL, &pstMsg->m_uData.m_stPlayParam.handle);
		}	

		DvbBuilderMonitorSearchStart(&pstMsg->m_uData.m_stPlayParam.tunerInfo, &pstMsg->m_uData.m_stPlayParam.handle);
        
		u16PmtPid = pstMsg->m_uData.m_stPlayParam.pmtpid;
		if(u16PmtPid != 0)//direct play
		{
			DvbPlayControlRecvPmt(u16PmtPid, ServiceHandle->serviceId);//monitor pmt
			if(!mwAvPlay(g_hPlay, u16PmtPid, ServiceHandle->serviceId, pstMsg->m_uData.m_stPlayParam.pPid, pstMsg->m_uData.m_stPlayParam.vPid, pstMsg->m_uData.m_stPlayParam.vType, pstMsg->m_uData.m_stPlayParam.aPid, pstMsg->m_uData.m_stPlayParam.aType))
			{
				mwAvSetStereoMode(pstMsg->m_uData.m_stPlayParam.stero);//do it in ui thread next
				mwAvSetVolume(pstMsg->m_uData.m_stPlayParam.vol);//do it in ui thread next
			}
			
			mwDebug("DvbPlayControlStartMsg send capmt \r\n");
			mwCIStartDescrable(pstMsg->m_uData.m_stPlayParam.pmt, pstMsg->m_uData.m_stPlayParam.pmtlen);
			pstManager->m_u32CapmtSended = 1;
			pstManager->m_u32PmtCrc = SiPsiGetSectionCrc(pstMsg->m_uData.m_stPlayParam.pmt);
			mwOsSleep(200);
			pstManager->m_eState = DVB_PLAY_PLAYING;
		}
		else//recv pmt
		{
			DvbPlayControlRecvPat();
			pstManager->m_eState = DVB_PLAY_RECV_PAT;
			pstManager->m_u32PmtCrc = 0;
			pstManager->m_u32CapmtSended = 0;
		}
		memcpy(&pstManager->m_stCurPlayParam, &pstMsg->m_uData.m_stPlayParam, sizeof(play_control_param_t));
	}
	else
	{
		mwDebug("DvbPlayControlStartMsg() - play the same channel\r\n");
	}
	DvbSetChannelPlayFlag(1);
		
	mwDebug("DvbPlayControlStartMsg() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int DvbPlayControlStopStateHandle(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = -1;
	
	mwDebug("DvbPlayControlStopStateHandle() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	switch(pstMsg->m_eType)
	{
		case START_PLAY:
		{
			mwDebug("DvbPlayControlStopStateHandle() - receive START_PLAY msg\r\n");
			s32Ret = DvbPlayControlStartMsg(pstManager, pstMsg);
			break;
		}
		default:
		{
			mwDebug("DvbPlayControlStopStateHandle() - receive other msg in stop state\r\n");
			break;
		}
	}
	mwDebug("DvbPlayControlStopStateHandle() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int DvbPlayControlWaitPatStateHandle(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = 0;
	
	mwDebug("DvbPlayControlWaitPatStateHandle() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	switch(pstMsg->m_eType)
	{
		case START_PLAY:
		{
			mwDebug("DvbPlayControlWaitPatStateHandle() - receive START_PLAY msg\r\n");
			s32Ret = DvbPlayControlStartMsg(pstManager, pstMsg);
			break;
		}
		case PAT_RECIEVED:
		{
			mwDebug("DvbPlayControlWaitPatStateHandle() - receive PAT_RECIEVED msg\r\n");
			s32Ret = DvbPlayControlGetPmtPid(pstMsg->m_uData.m_au8Data, pstManager->m_stCurPlayParam.handle.serviceId, &pstManager->m_stCurPlayParam.pmtpid);
			if(s32Ret == 0)
			{
				s32Ret = DvbPlayControlRecvPmt(pstManager->m_stCurPlayParam.pmtpid, pstManager->m_stCurPlayParam.handle.serviceId);
				pstManager->m_eState = DVB_PLAY_RECV_PMT;
			}
			else
			{
				mwError("DvbPlayControlWaitPatStateHandle() - get pmt pid error, pstManager->m_stCurPlayParam.handle.serviceId = %d\r\n", pstManager->m_stCurPlayParam.handle.serviceId);
			}
			break;
		}
		case STOP_PLAY:
		{
			mwDebug("DvbPlayControlWaitPatStateHandle() - receive STOP_PLAY msg\r\n");
			pstManager->m_eState = DVB_PLAY_STOP;
			pstManager->m_u32CapmtSended = 0;
			pstManager->m_u32PmtCrc = 0;
			memset(&pstManager->m_stCurPlayParam, 0, sizeof(pstManager->m_stCurPlayParam));
			DvbPlayControlStopPatPmt();
			mwAvStop(g_hPlay);
			DvbSetChannelPlayFlag(0);
			cas_stop_discrambling();
			break;
		}
		default:
		{
			mwDebug("DvbPlayControlWaitPatStateHandle() - receive other msg in wait pat state\r\n");
			break;
		}
	}
	mwDebug("DvbPlayControlWaitPatStateHandle() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int DvbPlayControlWaitPmtStateHandle(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = 0;
	unsigned short u16ServiceId;
	unsigned short u16PmtLen;
	unsigned int u32Crc;

	mwDebug("DvbPlayControlWaitPmtStateHandle() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	switch(pstMsg->m_eType)
	{
		case START_PLAY:
		{
			s32Ret = DvbPlayControlStartMsg(pstManager, pstMsg);
			break;
		}
		case PMT_RECIEVED:
		{
			u16ServiceId = SiPsiGetExtTableID(pstMsg->m_uData.m_au8Data);
			u16PmtLen = SiPsiGetSectionLength(pstMsg->m_uData.m_au8Data);
			u32Crc = SiPsiGetSectionCrc(pstMsg->m_uData.m_au8Data);
			if(u16ServiceId==pstManager->m_stCurPlayParam.handle.serviceId && (pstManager->m_u32CapmtSended==0||pstManager->m_u32PmtCrc!=u32Crc))
			{
				mwDebug("DvbPlayControlStateEvolution send capmt \r\n");
				mwCIStartDescrable(pstMsg->m_uData.m_au8Data, u16PmtLen+3);
				pstManager->m_u32CapmtSended = 1;
				if(pstManager->m_u32PmtCrc!=u32Crc && DvbPlayControlNeedReplay(&pstManager->m_stCurPlayParam, pstMsg->m_uData.m_au8Data)==0)
				{
					mwAvPlay(g_hPlay, pstManager->m_stCurPlayParam.pmtpid, pstManager->m_stCurPlayParam.handle.serviceId, pstManager->m_stCurPlayParam.pPid, pstManager->m_stCurPlayParam.vPid, pstManager->m_stCurPlayParam.vType, pstManager->m_stCurPlayParam.aPid, pstManager->m_stCurPlayParam.aType);
				}
				pstManager->m_u32PmtCrc = u32Crc;
				pstManager->m_eState = DVB_PLAY_PLAYING;
			}
			break;
		}
		case STOP_PLAY:
		{
			mwDebug("DvbPlayControlWaitPmtStateHandle() - receive STOP_PLAY msg\r\n");
			pstManager->m_eState = DVB_PLAY_STOP;
			pstManager->m_u32CapmtSended = 0;
			pstManager->m_u32PmtCrc = 0;
			memset(&pstManager->m_stCurPlayParam, 0, sizeof(pstManager->m_stCurPlayParam));
			DvbPlayControlStopPatPmt();
			mwAvStop(g_hPlay);
			DvbSetChannelPlayFlag(0);
			cas_stop_discrambling();
			break;
		}
		default:
		{
			mwDebug("DvbPlayControlWaitPmtStateHandle() - receive other msg in wait pmt state\r\n");
			break;
		}
	}
	mwDebug("DvbPlayControlWaitPmtStateHandle() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int DvbPlayControlPlayingStateHandle(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = 0;
	unsigned short u16ServiceId;
	unsigned short u16PmtLen;
	unsigned int u32Crc;
	
	mwDebug("DvbPlayControlPlayingStateHandle() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	switch(pstMsg->m_eType)
	{
		case START_PLAY:
		{
			s32Ret = DvbPlayControlStartMsg(pstManager, pstMsg);
			break;
		}
		case PMT_RECIEVED://only pmt receive
		{
			u16ServiceId = SiPsiGetExtTableID(pstMsg->m_uData.m_au8Data);
			u16PmtLen = SiPsiGetSectionLength(pstMsg->m_uData.m_au8Data);
			u32Crc = SiPsiGetSectionCrc(pstMsg->m_uData.m_au8Data);
			if(u16ServiceId==pstManager->m_stCurPlayParam.handle.serviceId && (pstManager->m_u32CapmtSended==0||pstManager->m_u32PmtCrc!=u32Crc))
			{
				mwDebug("DvbPlayControlStateEvolution send capmt \r\n");
				mwCIStartDescrable(pstMsg->m_uData.m_au8Data, u16PmtLen+3);
				pstManager->m_u32CapmtSended = 1;
				if(pstManager->m_u32PmtCrc!=u32Crc && DvbPlayControlNeedReplay(&pstManager->m_stCurPlayParam, pstMsg->m_uData.m_au8Data)==0)
				{
					mwAvPlay(g_hPlay, pstManager->m_stCurPlayParam.pmtpid, pstManager->m_stCurPlayParam.handle.serviceId, pstManager->m_stCurPlayParam.pPid, pstManager->m_stCurPlayParam.vPid, pstManager->m_stCurPlayParam.vType, pstManager->m_stCurPlayParam.aPid, pstManager->m_stCurPlayParam.aType);
				}
				pstManager->m_u32PmtCrc = u32Crc;
				mwOsSleep(200);
			}
			break;
		}
		case STOP_PLAY:
		{
			mwDebug("DvbPlayControlPlayingStateHandle() - receive STOP_PLAY msg\r\n");
			pstManager->m_eState = DVB_PLAY_STOP;
			pstManager->m_u32CapmtSended = 0;
			pstManager->m_u32PmtCrc = 0;
			memset(&pstManager->m_stCurPlayParam, 0, sizeof(pstManager->m_stCurPlayParam));
			DvbPlayControlStopPatPmt();
			mwAvStop(g_hPlay);
			DvbSetChannelPlayFlag(0);
			cas_stop_discrambling();
			break;
		}
		default:
		{
			mwDebug("DvbPlayControlPlayingStateHandle() - receive other msg in wait pmt state\r\n");
			break;
		}
	}
	mwDebug("DvbPlayControlPlayingStateHandle() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

static int DvbPlayControlStateEvolution(play_control_manager_t* pstManager, play_control_msg_t* pstMsg)
{
	int s32Ret = -1;
	unsigned short u16PmtPid;
	unsigned short u16PmtLen;
	unsigned short u16ServiceId;
	
	mwDebug("DvbPlayControlStateEvolution() - entry, pstManager = %p, pstMsg = %p\r\n", pstManager, pstMsg);
	switch(pstManager->m_eState)
	{
		case DVB_PLAY_STOP:
			s32Ret = DvbPlayControlStopStateHandle(pstManager, pstMsg);
			break;
		case DVB_PLAY_RECV_PAT:
			s32Ret = DvbPlayControlWaitPatStateHandle(pstManager, pstMsg);
			break;
		case DVB_PLAY_RECV_PMT:
			s32Ret = DvbPlayControlWaitPmtStateHandle(pstManager, pstMsg);
			break;
		case DVB_PLAY_PLAYING:
			s32Ret = DvbPlayControlPlayingStateHandle(pstManager, pstMsg);
			break;
		default:
			mwError("DvbPlayControlStateEvolution() - error state\r\n");
			break;
	}
	mwDebug("DvbPlayControlStateEvolution() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

static void DvbPlayControl_Task()
{
	play_control_msg_t stMsg;
	play_control_manager_t stManager;

	mwDebug("DvbPlayControl_Task() - entry\r\n");
	memset(&stManager, 0, sizeof(stManager));
	stManager.m_eState = DVB_PLAY_STOP;
	while(1)
	{
		if(mwOsReceiveMessage(hMsgquePlayControl, &stMsg, sizeof(play_control_msg_t), -1)==0)
		{
			DvbPlayControlStateEvolution(&stManager, &stMsg);
		}
		else
		{
			mwDebug("DvbPlayControl_Task() - recieve msgqueue error\r\n");
		}
	}
	mwDebug("DvbPlayControl_Task() - return\r\n");
}

int DvbPlayNewChannel(play_control_param_t* pstChannel)
{
	int ret;
	play_control_msg_t stMsg;
	
	mwDebug("DvbPlayNewChannel entry - pstChannel = %p, handle[tsid:%x, netid:%x, sid:%x, freq:%d]\r\n", 
					pstChannel, pstChannel->handle.tsId, pstChannel->handle.netId, pstChannel->handle.serviceId, pstChannel->handle.frequence);
	
	mwOsEmptyMessage(hMsgquePlayControl);
	stMsg.m_eType = START_PLAY;
	memcpy(&stMsg.m_uData.m_stPlayParam, pstChannel, sizeof(play_control_param_t));
	ret = mwOsSendMessage(hMsgquePlayControl, &stMsg, sizeof(stMsg), 0);
	if(ret != 0)
	{
		mwDebug(">>>DvbPlayNewChannel call mwOsSendMessage ret=%d\n",ret);
	}
	
	mwDebug("DvbPlayNewChannel return\r\n");
	return ret;
}

int DvbPlayStop()
{
	int ret;
	play_control_msg_t stMsg;
	DvbBuilderMonitorSearchStop();
	mwOsEmptyMessage(hMsgquePlayControl);
	stMsg.m_eType = STOP_PLAY;
	ret = mwOsSendMessage(hMsgquePlayControl, &stMsg, sizeof(stMsg), 0);
	if(ret != 0)
	{
		mwDebug(">>>DvbPlayStop call mwOsSendMessage ret=%d\n",ret);
	}

	return ret;
}

int DvbPlayTaskInit()
{	
	dvb_handle_t  playControlTaskHandle;
	int ret;
	hMsgquePlayControl = mwOsCreateMessage(5,sizeof(play_control_msg_t));
	if(!hMsgquePlayControl)
	{
		return -1;
	}
	ret = mwOsCreateTask("DvbPlayTask", 1, 0x8000, &playControlTaskHandle, TRUE, (task_entry_t)DvbPlayControl_Task, NULL);

	return ret;
}

